#ifndef U2DataStreamFileStream_H
#define U2DataStreamFileStream_H

#include "U2PreRequest.h"
#include "U2DataStream.h"


U2EG_NAMESPACE_BEGIN


class _U2Share U2DataStreamFileStream : public U2DataStream
{
public:
	/** Construct a read-only stream from an STL stream
    @param s Pointer to source stream
    @param freeOnClose Whether to delete the underlying stream on 
        destruction of this class
    */
	U2DataStreamFileStream(std::ifstream* s, 
        bool freeOnClose = true, 
        Endian endian = ENDIAN_NATIVE);
	/** Construct a read-write stream from an STL stream
	@param s Pointer to source stream
	@param freeOnClose Whether to delete the underlying stream on 
	destruction of this class
	*/
	U2DataStreamFileStream(std::fstream* s, 
		bool freeOnClose = true, 
        Endian endian = ENDIAN_NATIVE);

	/** Construct named read-only stream from an STL stream
    @param name The name to give this stream
    @param s Pointer to source stream
    @param freeOnClose Whether to delete the underlying stream on 
        destruction of this class
    */
	U2DataStreamFileStream(const U2String& name, 
        std::ifstream* s, 
        bool freeOnClose = true, 
        Endian endian = ENDIAN_NATIVE);

	/** Construct named read-write stream from an STL stream
	@param name The name to give this stream
	@param s Pointer to source stream
	@param freeOnClose Whether to delete the underlying stream on 
	destruction of this class
	*/
	U2DataStreamFileStream(const U2String& name, 
		std::fstream* s, 
		bool freeOnClose = true, 
        Endian endian = ENDIAN_NATIVE);

	/** Construct named read-only stream from an STL stream, and tell it the size
    @remarks
        This variant tells the class the size of the stream too, which 
        means this class does not need to seek to the end of the stream 
        to determine the size up-front. This can be beneficial if you have
        metadata about the contents of the stream already.
    @param name The name to give this stream
    @param s Pointer to source stream
    @param size Size of the stream contents in bytes
    @param freeOnClose Whether to delete the underlying stream on 
        destruction of this class. If you specify 'true' for this you
		must ensure that the stream was allocated using OGRE_NEW_T with 
		MEMCATEGRORY_GENERAL.
    */
	U2DataStreamFileStream(const U2String& name, 
        std::ifstream* s, 
        size_t size, 
        bool freeOnClose = true, 
        Endian endian = ENDIAN_NATIVE);

	/** Construct named read-write stream from an STL stream, and tell it the size
	@remarks
	This variant tells the class the size of the stream too, which 
	means this class does not need to seek to the end of the stream 
	to determine the size up-front. This can be beneficial if you have
	metadata about the contents of the stream already.
	@param name The name to give this stream
	@param s Pointer to source stream
	@param size Size of the stream contents in bytes
	@param freeOnClose Whether to delete the underlying stream on 
	destruction of this class. If you specify 'true' for this you
	must ensure that the stream was allocated using OGRE_NEW_T with 
	MEMCATEGRORY_GENERAL.
	*/
	U2DataStreamFileStream(const U2String& name, 
		std::fstream* s, 
		size_t size, 
		bool freeOnClose = true, 
        Endian endian = ENDIAN_NATIVE);

	~U2DataStreamFileStream();

	/** @copydoc DataStream::read
	*/
	size_t read(void* buf, size_t count);

	/** @copydoc DataStream::write
	*/
	size_t write(const void* buf, size_t count);

	/** @copydoc DataStream::readLine
	*/
    size_t readLine(char* buf, size_t maxCount, const U2String& delim = "\n");
	
	/** @copydoc DataStream::skip
	*/
	void skip(long count);

	/** @copydoc DataStream::seek
	*/
    void seek( size_t pos );

	/** @copydoc DataStream::tell
	*/
	size_t tell(void) const;

	/** @copydoc DataStream::eof
	*/
    bool eof(void) const;

    /** @copydoc DataStream::close
    */
    void close(void);

protected:
    /// Reference to source stream (read)
    std::istream* mInStream;
    /// Reference to source file stream (read-only)
    std::ifstream* mFStreamRO;
    /// Reference to source file stream (read-write)
    std::fstream* mFStream;
    bool mFreeOnClose;	

    void determineAccess();
};


U2EG_NAMESPACE_END

#endif